/*  
 * Last Edited: 06/07/2013 by Ching-Ting
 * 
 * [NOTE]: To set up propertyChangeListener, setFlag() method MUST be called by
 * passing in a JLabel.
 */
package View;

import java.util.Calendar;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import Model.Conference;
import Model.Controller;
import Model.Paper;
import Model.User;

/**
 * This class populates the list of inputs into a table to be put onto the GUI.
 * 
 * @author Ching-Ting Huang
 * @version UWTCSS 360, Spring 2013. 3-squared-software-systems.
 */
public class ScrollPane {

	private Controller controller;
	private DefaultTableModel model;
	private JTable table;
	private JScrollPane scrollPane;
	private JLabel flag;
	private Object[][] input;
	private int row;

	/**
	 * Depending on the type of input, different list is being put into a 2D-array in order
	 * to populate a JTable that will later be put into JScrollPane to be displayed.
	 * 
	 * @param control is the Model Controller.
	 * @param para is the type of inputs being passed in in String representation: Conference(conf),
	 * 		  ProgramChair(pc), SubprogramChair(spc), Reviewer(rev), Author(auth).
	 * @author Ching-Ting Huang
	 */
	public ScrollPane(final Controller control, final String para) {
		row = -1;
		controller = control;
		Object[][] data = getList(para);
		String[] header = getHeader(para);
		input = data;

		model = new DefaultTableModel(data, header) {
			private static final long serialVersionUID = -1411446165832277578L;

			@Override
			public boolean isCellEditable(int row, int column) {
				//make all cells editable = false
				return false;
			}
		};

		table = new JTable(model);
		tableSetUp(table, para);
		scrollPane = new JScrollPane(table);
		table.setFillsViewportHeight(true);
	} //Table

	/**
	 * Sets up functions of the JTable: enable only row selection, set cell editable false,
	 * draw horizontal & vertical lines between column and row, one selection at an instance.
	 * 
	 * @param table is the JTable.
	 * @author Ching-Ting Huang
	 */
	private void tableSetUp(final JTable table, final String type) {
		table.setCellSelectionEnabled(false);
		table.setDragEnabled(false);
		table.setRowSelectionAllowed(true);
		table.setShowHorizontalLines(true);
		table.setShowVerticalLines(true);
		table.setAutoCreateRowSorter(true);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		if (type.equals("conf")) {
			//no extra column to hide in this case
		} else {
			table.removeColumn(table.getColumn("ID"));	//hide this column from view
		}
		
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				if (!e.getValueIsAdjusting()) {
					row = table.getSelectedRow();
					if (row >= 0) {
						if (flag != null) {
							flag.setText(flag.getText() + "+");
						}
					}
				}
			}

		});
	} //tableSetup

	/**
	 * Putting list of conference into 2D-array as well as its date, name and PC.
	 * 
	 * @param list is all the conferences created.
	 * @return 2D-array of the conferences and its meta-data.
	 * @author Ching-Ting Huang
	 */
	private Object[][] putConferenceToArray(final List<Conference> list) {
		Object[][] data = new Object[list.size()][3];
		for (int i = 0; i < list.size(); i++) {
			int month = list.get(i).getConferenceDate().getDateMonth();
			int day = list.get(i).getConferenceDate().getDateDay();
			int year = list.get(i).getConferenceDate().getDateYear();

			data[i][0] = year + "/" + month + "/" + day;
			data[i][1] = list.get(i).getConferenceName();
			data[i][2] = list.get(i).getProgramChair().getfullname();
		}
		return data;
	} //putConferenceToArray

	/**
	 * Putting list of all papers for that particular Program Chair into 2D-array
	 * as well as the paper's title, author and assigned Subprogram Chair.
	 * 
	 * @param list is all the papers submitted to the conference the Program Chair
	 * 		  is responsible for.
	 * @return 2D-array of the papers and its meta-data.
	 * @author Ching-Ting Huang
	 */
	private Object[][] putPCToArray(final List<Paper> list) {
		Object[][] data = new Object[list.size()][5];
		for (int i = 0; i < list.size(); i++) {
			data[i][0] = list.get(i).getTitle();
			data[i][1] = list.get(i).getName();
			//Edited by Daniel
			data[i][4] = list.get(i);
			//Edited by Jonathan
			if(list.get(i).getSPC() != null) {                                                                         // TEMPORARY FIX for unassigned SPC NullPointerException
				data[i][2] = list.get(i).getSPC().getfullname();
			} else {
				data[i][2] = "NOT ASSIGNED";
			}
			
			if(list.get(i).getReviewers().isEmpty()) {
				data[i][3] = "NOT ASSIGNED";
			} else {
				String reviewers = "";
				for (User u : list.get(i).getReviewers()) {
					reviewers = reviewers + u.getfullname() + ", ";
				}
				reviewers = reviewers.substring(0, reviewers.length()-2);
				data[i][3] = reviewers;
			}
			
			
		}
		return data;
	} //putPCToArray

	/**
	 * Putting list of all papers for that particular Subprogram Chair into 2D-array
	 * as well as the paper's title, author and assigned reviewers.
	 * 
	 * @param list is all the papers assigned to the Subprogram Chair by the Program Chair.
	 * @return 2D-array of the papers and its meta-data.
	 * @author Ching-Ting Huang
	 */
	private Object[][] putSPCToArray(final List<Paper> list) {
		Object[][] data = new Object[list.size()][4];
		for (int i = 0; i < list.size(); i++) {
			data[i][0] = list.get(i).getTitle();
			data[i][1] = list.get(i).getName();
			//Edited by Daniel
			data[i][3] = list.get(i);
			//Edited by Jonathan
			if(list.get(i).getReviewers().isEmpty()) {
				data[i][2] = "NOT ASSIGNED";
			} else {
				String reviewers = "";
				for (User u : list.get(i).getReviewers()) {
					reviewers = reviewers + u.getfullname() + ", ";
				}
				reviewers = reviewers.substring(0, reviewers.length()-2);
				data[i][2] = reviewers;
			}
			
		}
		return data;
	} //putSPCToArray

	/**
	 * Putting list of all papers for that particular reviewer into 2D-array
	 * as well as the paper's title and author.
	 * 
	 * @param list is all the papers assigned to the reviewer by Subprogram Chair.
	 * @return 2D-array of the papers and its meta-data.
	 * @author Ching-Ting Huang
	 */
	private Object[][] putRevToArray(final List<Paper> list) {
		Object[][] data = new Object[list.size()][3];
		for (int i = 0; i < list.size(); i ++) {
			data[i][0] = list.get(i).getTitle();
			data[i][1] = list.get(i).getName();
			//Edited by Daniel
			data[i][2] = list.get(i);
		}
		return data;
	} //putRevToArray

	/**
	 * Putting list of all papers for that particular author into 2D-array
	 * as well as the papers' title, submitted conference and date of submission.
	 * 
	 * @param list is all the papers the author has submitted.
	 * @return 2D-array of the papers and its meta-data.
	 * @author Ching-Ting Huang
	 */
	private Object[][] putAuthToArray(final List<Paper> list) {
		Object[][] data = new Object[list.size()][4];
		for (int i = 0; i < list.size(); i++) {
			Calendar date = Calendar.getInstance();
			date.setTime(list.get(i).getLatestRevision());
			int month = date.get(Calendar.MONTH) + 1;
			int day = date.get(Calendar.DATE);
			int year = date.get(Calendar.YEAR);

			data[i][0] = list.get(i).getTitle();
			data[i][1] = list.get(i).getConference().getConferenceName();
			data[i][2] = year + "/" + month + "/" + day;
			//Edited by Daniel
			data[i][3] = list.get(i);
		}
		return data;
	} //putAuthToArray

	/**
	 * Setup table header depending on type of input.
	 * 
	 * @param type is the list type passed in (conference, paper).
	 * @return string array as table header.
	 * @author Ching-Ting Huang
	 */
	private String[] getHeader(final String type) {
		String[] header = null;
		if (type.equals("conf")) {
			header = new String[]{"Date", "Conference Name", "Program Chair"};
		} else if (type.equals("pc")) {
			header = new String[]{"Title", "Author", "Subprogram Chair", "Assigned Reviewer(s)", "ID"};
		} else if (type.equals("spc")) {
			header = new String[]{"Title", "Author", "Assigned Reviewer(s)", "ID"};
		} else if (type.equals("rev")) {
			header = new String[]{"Title", "Author", "ID"};
		} else if (type.equals("auth")) {
			header = new String[]{"Title", "Submitted Conference", "Date Submitted", "ID"};
		}
		return header;
	} //getHeader

	/**
	 * Depending on the input type, different lists are used to populate 2D array that
	 * will be displayed on the JTable/JScrollPane.
	 * 
	 * @param type is the input type: conference(conf), program chair(pc), subprogram chair(spc),
	 * 		  reviewer(rev), author(auth).
	 * @return 2D-array representation of the input list.
	 * @author Ching-Ting Huang
	 */
	private Object[][] getList(final String type) {
		Object[][] data = null;
		if (type.equals("conf")) {
			data = putConferenceToArray(controller.getConferenceList());
		} else if (type.equals("pc")) {
			data = putPCToArray(controller.getPCPapers());
		} else if (type.equals("spc")) {
			data = putSPCToArray(controller.getSPCPapers());
		} else if (type.equals("rev")) {
			data = putRevToArray(controller.getPeerReviewPapers());
		} else if (type.equals("auth")) {
			data = putAuthToArray(controller.getUserSubmittedPapers());
		}
		return data;
	} //getList

	/**
	 * This is a JLabel made by caller with added propertyChangeListener. When this label
	 * is passed into this class as a field and its text is later changed when a row is
	 * selected in the table, the propertyChangeListener will notify the change on the 
	 * caller side.
	 * 
	 * @param label is the 'flag' to notify the caller a row has been selected in the table.
	 * @author Ching-Ting Huang
	 */
	public void setFlag(final JLabel label) {
		flag = label;
	} //setFlag

	/**
	 * The current selected row in the table.
	 * 
	 * @return the selected row index in the table.
	 * @author Ching-Ting Huang
	 */
	public int getSelectedRowNum() {
		return row;
	} //getRowNum

	/**
	 * Gets the specified row in the 2D-array
	 * 
	 * @return the row of data from the 2D-array.
	 * @author Ching-Ting Huang
	 */
	public Object[] getRow(final int row) {
		int size = input[row].length;
		Object[] result = new Object[size];
		for (int i = 0; i < size; i++) {
			if (input[row][i] != null) {
				result[i] = input[row][i];
			}
		}
		return result;
	} //getInput

	/**
	 * Add additional items into the JTable/JScrollPane.
	 * 
	 * @param object is the array of data specified by the caller.
	 * @author Ching-Ting Huang
	 */
	public void addToTable(Object[] object) {
		/* Object[] object =
		 * Conference tab: Date, Conference Name, Program Chair Name
		 * Program Chair tab: Paper Title, Author Name, Subprogram Chair Name
		 * Subprogram Chair tab: Paper Title, Author Name, Reviewers List
		 * Reviewer tab: Paper Title, Author Name
		 * Author tab: Paper Title, Submitted Conference Name, Submission Date
		 */
		model.addRow(object);	
		int row = model.getRowCount();
		int col = model.getColumnCount();
		Object[][] temp = new Object[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				temp[i][j] = model.getValueAt(i, j);
			}
		}
		input = temp;
	} //addToTable

	/**
	 * Remove item in 2D-array at index. If looking for selected index, can call
	 * getSelectedRowNum() to get index.
	 * 
	 * @param index is the index number of the item to be deleted from the table.
	 * @return check if item is properly removed.
	 * @author Ching-Ting Huang
	 */
	public boolean removeFromTable(final int index) {
		boolean papersStillExist  = true;
		model.removeRow(index);
		int row = model.getRowCount();
		int col = model.getColumnCount();
		Object[][] temp = new Object[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				temp[i][j] = model.getValueAt(i, j);
			}
		}
		
		//Edited by Daniel, Jonathan
		input = temp;
		controller.getCurrentUser().getAuthorPapers().remove(index); 
		if(controller.getCurrentUser().getAuthorPapers().size() <  1) { // If no papers exists after Unsubmitting a paper, then the user is no longer an author
			controller.getCurrentUser().setPermission(0, false);//remove author role from user
			controller.changedCurrentUserPermissions();
			papersStillExist = false;

		}
		return papersStillExist;
	} //removeFromTable

	/**
	 * Gets the current scrollpane.
	 * 
	 * @return JScrollPane.
	 * @author Ching-Ting Huang
	 */
	public JScrollPane getScrollPane() {
		return scrollPane;
	} //getScrollPane
} //class
